import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage } from 'element-plus'
import {getToken} from "@/utils/token.js";
import {tansParams} from "@/utils";
import NProgress from "@/utils/progress.js";

export const errorCode = {
    '401': '认证失败，无法访问系统资源',
    '403': '当前操作没有权限',
    '404': '访问资源不存在',
    'default': '系统未知错误，请反馈给管理员'
}

// 是否显示重新登录
export let isRelogin = { show: false };

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 对应国际化资源文件后缀
axios.defaults.headers['Content-Language'] = 'zh_CN'
// 创建axios实例
const service = axios.create({
    // axios中请求配置有baseURL选项，表示请求URL公共部分
    baseURL: import.meta.env.VITE_APP_BASE_API,
    // 超时
    timeout: 10000
})

// request拦截器
service.interceptors.request.use(config => {
    NProgress.start();

    // 是否需要设置 token
    const isToken = (config.headers || {})?.isToken ?? true
    
    // 是否需要防止数据重复提交
    const isRepeatSubmit = (config.headers || {})?.repeatSubmit ?? true
    if (getToken() && isToken) {
        config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    
    // get请求映射params参数
    if (config.method === 'get' && config.params) {
        let url = config.url + '?' + tansParams(config.params);
        url = url.slice(0, -1);
        config.params = {};
        config.url = url;
    }
    
    // post和put默认开启 防重提交
    if (isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
        // 请求地址 + 请求数据 + 当前系统时间
        const requestObj = {
            url: config.url,
            data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
            time: new Date().getTime()
        }
        // 从会话中获取上一次请求的缓存
        let lastRequest = useSessionStorage("lastRequest", {});
        const s_url = lastRequest.value?.url;                // 请求地址
        const s_data = lastRequest.value?.data;              // 请求数据
        const s_time = lastRequest.value?.time;              // 请求时间
        const interval = 1000;                       // 间隔时间(ms)，小于此时间视为重复提交
        
        // 如果是同样的请求但是间隔时间小于1s
        if (s_url === requestObj.url && s_data === requestObj.data && requestObj.time - s_time < interval ) {
            const message = '数据正在处理，请勿重复提交';
            console.warn(`[${s_url}]: ` + message)
            return Promise.reject(new Error(message))
        } else {
            // 将本次请求存入会话存储
            lastRequest.value = requestObj
        }
    }
    return config
}, error => {
    console.error(error)
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
        NProgress.done()
        // 未设置状态码则默认成功状态
        const code = res.data.code || 200;
        // 获取错误信息
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        // 二进制数据则直接返回
        if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
            return res.data
        }
        if (code === 401) {
            if (!isRelogin.show) {
                isRelogin.show = true;
                ElMessageBox.confirm(
                        '登录状态已过期，您可以继续留在该页面，或者重新登录',
                        '系统提示',
                        { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
        
                    isRelogin.show = false;
                    useUserStore().logOut().then(() => {
                        location.href = '/index';
                    })
        
                }).catch(() => {
                    isRelogin.show = false;
                });
            }
            return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
        } else if (code === 500) {
            ElMessage({ message: msg, type: 'error' })
            return Promise.reject(new Error(msg))
        } else if (code === 601) {
            ElMessage({ message: msg, type: 'warning' })
            return Promise.reject(new Error(msg))
        } else if (code !== 200) {
            ElNotification.error({ title: msg })
            return Promise.reject('error')
        } else {
            return  Promise.resolve(res.data)
        }
    },error => {
            let { message } = error;
            if (message === "Network Error") {
                message = "后端接口连接异常";
            } else if (message.includes("timeout")) {
                message = "系统接口请求超时";
            } else if (message.includes("Request failed with status code")) {
                message = "系统接口" + message.slice(message.length - 3) + "异常";
            }
            ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
            return Promise.reject(error)
        }
        
)

export default service
